//命令行解释器模拟实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>

#define NUM 1024
#define OPT_NUM 64

char lineCommand[NUM];//存放输入指令
char* myargv[OPT_NUM];
int lastCode=0;
int lastSig=0;

int main()
{
  while(1)
  {

      printf("用户名@主机名：当前路径# ");
      fflush(stdout);

      //获取用户输入，以\n结束
      char* s=fgets(lineCommand,sizeof(lineCommand)-1,stdin);
      assert(s);
      (void)s;
      //由于输入以\n结束，此处需要清理
      lineCommand[strlen(lineCommand)-1]=0;
      //printf("test==%s\n",lineCommand);

      //对输入的字符串切割，换成一条条指令
      //strtok如果找不到会返回NULL
      //ls -a -l -i ->"ls" "-a" "-l"
      myargv[0]=strtok(lineCommand," ");
      int i=1;
      if(myargv[0]!= NULL && strcmp(myargv[0],"ls")==0)
      {
        myargv[i++]=(char*)"--color=auto";
      }
      
      //循环切割，直到没有“ ”，返回NULL
      while(myargv[i++]=strtok(NULL," "));
      
      //cd ..命令,不需要创建子进程，让shell自己去执行调用系统接口
      //内建/内置命令
      if(myargv[0]!= NULL && strcmp(myargv[0],"cd")==0)
      {
        if(myargv[1]!=NULL)
        {
          //切换进程的工作目录（当前路径）,这是父进程调用的，不需要创建子进程
            chdir(myargv[1]);
        }
         continue;
      }
      //echo $?
      if(myargv[0]!= NULL && myargv[1] != NULL && strcmp(myargv[0],"echo")==0)
      {
          if(strcmp(myargv[1],"$?")==0)
          {
              printf("%d,%d\n",lastCode,lastSig);
          }
          else
          {
            printf("%s\n",myargv[1]);

          }
          continue;
      }
   
#ifdef DEBUG
        for(int i = 0 ; myargv[i]; i++)
        {
            printf("myargv[%d]: %s\n", i, myargv[i]);
        }
#endif
        //执行命令
        pid_t id=fork();
        assert(id != -1);
        if(id==0)
        {
          execvp(myargv[0],myargv);
          exit(1);//只要返回，必出错
        }
        int status=0;
        pid_t ret=waitpid(id,&status,0);
        assert(ret>0);
        printf("pid_t==%d",ret);
        (void)ret;
        lastCode=((status>>8)& 0xFF);
        lastSig=(status & 0x7F);
     }
}

